<!DOCTYPE html>
<html>
<head>
    <title></title>
    <link rel="stylesheet" type="text/css" href="../公用CSS文件/all.css" />
    <script type="text/javascript" src="../js/jquery.min.js"></script>
    <script type="text/javascript" src="../js/js.js"></script>
    <meta charset="utf-8">
    <style type="text/css">
        table{min-width:80%}
    </style>
</head>
<body>
<div class="dt">Redis简介</div>
<ul>
    <li>Redis是一个开源的使用ANSIC语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库</li>
    <li>Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务，默认以6379端口对外提供服务</li>
</ul>

<div class="dt">Redis的特点</div>
<ul>
    <div class="ltable showimg">Redis优点</div>
    <div class="img">
        <table>
            <tr>
                <th>优点</th><th>说明</th><th>对比和说明</th>
            </tr>
            <tr>
                <td>性能极高</td>
                <td>Redis能读的速度是110000次/s,写的速度是81000次/s </td>
                <td>Memcacheddd能调用多核处理数据，数据量大时性能更优，Redis在数据量小时更优</td>
            </tr>
            <tr>
                <td>数据类型丰富</td>
                <td>支持String、Hash、List、set、Sorted Set多种数据类型</td>
                <td>Memcached所有数据类型都是类似Redis的String类型</td>
            </tr>
            <tr>
                <td>原子性</td>
                <td>Redis单个操作都是原子性的，多个操作通过multi和exec指令包起来也能支持原子性</td>
                <td>Memcached不支持原子性</td>
            </tr>
            <tr>
                <td>丰富的特性</td>
                <td>Redis还支持 publish/subscribe, brpop通知, key过期, 管道技术(多次请求1次返回)等等特性。</td>
            </tr>
        </table>
        <li>多条Redis命令的事务机制只检查语法错误判断不执行并没有保证原子性的其他机制，所以Redis事务的执行并不是原子性的。</li>
    </div>

    <div class="ltable showimg">Redis与其他key-value数据库的不同</div>
    <div class="img">
        <li>Redis有着更为复杂的数据结构并且提供对他们的原子性操作，且数据结构相对透明</li>
        <li>Redis运行在内存中但是可以持久化到磁盘</li>
    </div>
</ul>

<div class="dt">Redis目录文件说明</div>
<ul>
    <table >
        <tr>
            <th>文件</th><th>说明</th>
        </tr>
        <tr>
            <td>redis-server.exe</td><td>服务程序</td>
        </tr>
        <tr>
            <td>redis.conf</td><td>redis配置文件<span style="color: red">@！</span></td>
        </tr>
        <tr>
            <td>redis.cli.exe</td><td>命令行客户端</td>
        </tr>
        <tr>
            <td>redis-check-aof.exe</td><td>更新日志检查</td>
        </tr>
        <tr>
            <td>redis-benchmark.exe</td><td>性能测试，用以模拟同时由N个客户端发送M个 SETs/GETs 查询 (类似于 Apache的 ab 工具)</td>
        </tr>
    </table>
    <li>redis的配置文件有两个，不带service为当做普通程序启动时的配置，带server的是作为服务启动的配置</li>
</ul>

<div class="dt">Redis数据类型</div>
<ul>
    <div class="ltable showimg">Redis数据类型</div>
    <div class="img">
        <table>
            <tr>
                <th>类型</th><th>说明</th><th>存储方式</th>
            </tr>
            <tr>
                <td>String(字符串)</td>
                <td>最基本的类型，你可以理解成与Memcachedd一模一样的类型</td>
                <td>二进制存储，可以存储文件</td>
            </tr>
            <tr>
                <td>Hash(哈希散列)</td>
                <td>string 类型的 field 和 value 的映射表，可以快速修改其中的一部分数据</td>
                <td>HashMap</td>
            </tr>
            <tr>
                <td>List(队列)</td>
                <td>一个双向链表结构的数据，也支持区间操作、索引位读取等操作</td>
                <td>链表</td>
            </tr>
            <tr>
                <td>set(集合)</td>
                <td>set对外提供的功能与list类似是一个列表的功能，特殊之处在于set是可以自动排重的</td>
                <td>value永远为null的HashMap</td>
            </tr>
            <tr>
                <td>Stored set(有序集合)</td>
                <td>自动排序也可通过操作score排序的set集合</td>
                <td>HashMap和skipList</td>
            </tr>
        </table>
        <li>list数据类型，除了通常的数据操作，还提供了brpop指令用于异步出栈(无数据一直等到有数据)</li>
    </div>

    <div class="ltable showimg">Hash和Hash算法</div>
    <div class="img">
        <table>
            <tr>
                <th>概念</th><th>说明</th>
            </tr>
            <tr>
                <td>哈希算法</td>
                <td>一类算法的统称，也叫散列算法，满足这样的关系：f（data）=key，输入任意长度的data数据，经过该函数处理后得到一个定长的数据key，并且无法由key逆推出data，这样的算法就叫哈希算法</td>
            </tr>
            <tr>
                <td>哈希表</td>
                <td>一个数据集，经过哈希算法处理后得到key的数据集，然后将keys与原始数据进行一一映射就得到一个哈希表</td>
            </tr>
            <tr>
                <td>盐(Salt)</td>
                <td>在密码学中，是指通过在密码任意固定位置插入特定的字符串，让散列后的结果和使用原始密码的散列结果不相符，这种过程称之为“加盐”。该额外字符串称为盐值</td>
            </tr>
        </table>
        <li>哈希算法的三个特点中核心要求是可压缩、不可逆，无碰撞这个特点是理想模型，实际上几乎不可能完全做到</li>
        <li>java中也有一种叫Hashtable的数据结构，其实现核心是数组+</li>
        <li>以上结论来自于果壳网<a href="http://www.guokr.com/question/562532/">哈希表和哈希算法</a></li>
        <li>知乎网讨论，<a href="https://www.zhihu.com/question/20820286">什么是哈希算法</a></li>
    </div>
</ul>

<div class="dt">Redis数据操作</div>
<ul>
    <div class="ltable showimg">String字符串操作命令</div>
    <div class="img">
        <table>
            <tr>
                <th>命令</th><th>参数</th><th>作用</th>
            </tr>
            <tr>
                <td>set</td>
                <td>key value [EX 生存的秒（或PX 生存的毫秒）]  [NX或XX]</td>
                <td>设置一个key和value</td>
            </tr>
            <tr>
                <td>setex</td>
                <td>key 存续的秒 value</td>
                <td>设置一个key，并设置它的生存秒数</td>
            </tr>
            <tr>
                <td>psetex</td>
                <td>key 存续的毫秒 value </td>
                <td>设置一个key，并设置它的生存毫秒数</td>
            </tr>
            <tr>
                <td>mset</td>
                <td>key value [key value]</td>
                <td>同时设置多个key</td>
            </tr>
            <tr>
                <td>msetnx</td>
                <td>key value [key value] </td>
                <td>在所有key不存在时同时设置多个key</td>
            </tr>

            <tr>
                <td>setrange</td>
                <td>key start（开始的位置offset） value </td>
                <td>改变一个key的值，从start开始替换原值（替换新值长度个字符）</td>
            </tr>
            <tr>
                <td>get </td>
                <td>key（键名）</td>
                <td>获取一个键的value</td>
            </tr>
            <tr>
                <td>mget</td>
                <td> key [key...]</td>
                <td>获取多个键的value</td>
            </tr>
            <tr>
                <td>getrange</td>
                <td> key start开始偏移量 end结束偏移量</td>
                <td>获取key的从start到end的一部分的value</td>
            </tr>
            <tr>
                <td>strlen</td>
                <td>key键名</td>
                <td>返回key的值的长度</td>
            </tr>
            <tr>
                <td>incr</td>
                <td>key</td>
                <td>让key的value自增1</td>
            </tr>
            <tr>
                <td>incrby</td>
                <td>key键名 自增量（可以为负）</td>
                <td>让key的value增加一个数</td>
            </tr>
            <tr>
                <td>incrbyfloat</td>
                <td>key键名 自增量（可以为负）</td>
                <td>让key的value增加一个浮点数</td>
            </tr>
            <tr>
                <td>append</td>
                <td>key键名 value</td>
                <td>在key的值后面接上value，如果不存在相当于set一个新的key-value数据</td>
            </tr>
        </table>
        <li>在设置key时，指定追加NX为不存在时才进行设置，XX为存在时才修改</li>
    </div>

    <div class="ltable showimg">Hash散列表操作命令</div>
    <div class="img">
        <table>
            <tr>
                <th>命令</th><th>参数</th><th>作用</th>
            </tr>
            <tr>
                <td>hset</td>
                <td>key哈希表名 field字段名 value值</td>
                <td>将哈希表key中的字段field的值设置为value</td>
            </tr>
            <tr>
                <td>hsetnx</td>
                <td>key哈希表名 field value</td>
                <td>仅在哈希表key不存在和该字段不存在时，将哈希表key中的字段field的值设置为value</td>
            </tr>
            <tr>
                <td>hmset</td>
                <td>key哈希表名 field字段名 value值[field字段名 value...]</td>
                <td>连续设置哈希表key的多个字段的值</td>
            </tr>
            <tr>
                <td>hget</td>
                <td>key哈希表名 field字段名</td>
                <td>获取存储在哈希表key中指定一个字段的值</td>
            </tr>
            <tr>
                <td>hmget</td>
                <td>key哈希表名 field字段名【field字段名...】</td>
                <td>获取存储在哈希表key中指定多个字段的值</td>
            </tr>
            <tr>
                <td>hgetall</td>
                <td>key哈希表名</td>
                <td>获取存储在哈希表key中所有字段的值</td>
            </tr>
            <tr>
                <td>hkeys</td>
                <td>key哈希表名</td>
                <td>获取所有哈希表的字段field</td>
            </tr>
            <tr>
                <td>hvals</td>
                <td>key哈希表名</td>
                <td>获取哈希表的所有值value</td>
            </tr>
            <tr>
                <td>hstrlen</td>
                <td>key哈希表名 field字段名</td>
                <td>获取指定表指定字段的value长度</td>
            </tr>
            <tr>
                <td>hlen</td>
                <td>key哈希表名</td>
                <td>获取指定表的字段个数</td>
            </tr>
            <tr>
                <td>hlen</td>
                <td>key哈希表名</td>
                <td>获取指定表的字段个数</td>
            </tr>
            <tr>
                <td>hexists</td>
                <td>key哈希表名 field</td>
                <td>获取哈希表该字段存在的个数（0或1）</td>
            </tr>
            <tr>
                <td>hdel</td>
                <td>key哈希表名 field【field...】</td>
                <td>删除哈希表的字段（1个或多个）</td>
            </tr>
            <tr>
                <td>hincrby</td>
                <td>key哈希表名 field 增量（int可以取负值）</td>
                <td>为哈希表的字段的值加上一个数</td>
            </tr>
            <tr>
                <td>hincrbyfloat</td>
                <td>key哈希表名 field 增量（float可以取负值）</td>
                <td>为哈希表的字段的值加上一个浮点数</td>
            </tr>
        </table>
    </div>

    <div class="ltable showimg">List队列操作命令</div>
    <div class="img">
        <table>
            <tr>
                <th>命令</th><th>参数</th><th>作用</th>
            </tr>
            <tr>
                <td>rpush</td>
                <td>key列表名 value[value...]</td>
                <td>在列表的右边添加一个或多个值（lpush为往左添加）</td>
            </tr>
            <tr>
                <td>rpushx</td>
                <td>key列表名 value[value...]</td>
                <td>仅在列表存在时，在列表中右边添加一个或多个值（lpush为往左添加）</td>
            </tr>
            <tr>
                <td>rpop</td>
                <td>key列表名</td>
                <td>删除列表往右数的最后一个（就是最左的那个，l就是往左数，最右的）</td>
            </tr>
            <tr>
                <td>blpop</td>
                <td>key列表名 timeout等待的时间 [key timeout...]</td>
                <td>移出并获取列表的最左的元素，如果没有元素会等待直到超时或者列表有元素</td>
            </tr>
            <tr>
                <td>rpoplpush</td>
                <td>key列表名 另外一个列表的名</td>
                <td>删除列表最后一个值并将其添加到另外一个列表的左边返回该值（只有这一种组合！待测试）</td>
            </tr>
            <tr>
                <td>blpoplpush</td>
                <td>key列表名 新列表名 timeout等待的时间 [key timeout...]</td>
                <td>移出最左的元素添加到新的列表，如果没有元素会等待直到超时或者列表有元素</td>
            </tr>
            <tr>
                <td>lindex</td>
                <td>key 索引位置</td>
                <td>通过索引返回列表的一个值</td>
            </tr>
            <tr>
                <td>lset</td>
                <td>key列表名  索引位置 value</td>
                <td>改变列表某个索引位置的value</td>
            </tr>
            <tr>
                <td>linsert</td>
                <td>key before或after 具体的值 value</td>
                <td>在列表的某个值之前或之后插入一个值）</td>
            </tr>
            <tr>
                <td>llen</td>
                <td>key列表名</td>
                <td>获取列表长度</td>
            </tr>
            <tr>
                <td>lrange</td>
                <td>key列表名 开始位置 结束位置</td>
                <td>获取列表指定范围的值</td>
            </tr>
            <tr>
                <td>lrem</td>
                <td>key列表名 count个数 移除的value </td>
                <td>移除列表元素，count为0时移除所有</td>
            </tr>
            <tr>
                <td>ltrim</td>
                <td>key列表名 start起始位置 stop结束位置 </td>
                <td>对列表进行修剪，只保留区间的值</td>
            </tr>
        </table>
        <li>带l的命令，可能是left，也可能是list的首字符，是哪一种看需求，</li>
        <li>ist列表的索引是右到左的，这是因为列表出栈的时候，从0开始取不需要计算列表长度，而从左出栈留下的值的索引不需要调整，阅读习惯恰恰是从左到右的</li>
        <li>队列list索引不可取负值</li>
    </div>

    <div class="ltable showimg">Set集合操作</div>
    <div class="img">
        <table>
            <tr>
                <th>命令</th><th>参数</th><th>作用</th>
            </tr>
            <tr>
                <td>sadd</td>
                <td>key 成员【成员...】</td>
                <td>向无序集合中添加元素</td>
            </tr>
            <tr>
                <td>scard</td>
                <td>key</td>
                <td>查看无序集合元素个数</td>
            </tr>
            <tr>
                <td>smembers</td>
                <td>key</td>
                <td>返回无序集合中所有成员</td>
            </tr>
            <tr>
                <td>sismember</td>
                <td>key member</td>
                <td>判断member元素是否是key无序集合的成员</td>
            </tr>
            <tr>
                <td>spop</td>
                <td>key 【count=1个数】</td>
                <td>随机删除并返回指定个数元素</td>
            </tr>
            <tr>
                <td>srandmember</td>
                <td>key 【count=1个数】</td>
                <td>随机返回指定个数元素</td>
            </tr>
            <tr>
                <td>smove</td>
                <td>key 要移动至的key 成员</td>
                <td>移动一个成员至另外一个集合，在新集合不存在时会创建</td>
            </tr>
            <tr>
                <td>sdiff</td>
                <td>key key1 key2...</td>
                <td>返回key1与其他无序集合的差集，只要value在任意两个集合中存在就不在差集之内</td>
            </tr>
            <tr>
                <td>sdiffstore</td>
                <td>要存储差集的key key1 key2..</td>
                <td>将key1与其他无序集合的差集存储到key中，返回差集的元素数</td>
            </tr>
            <tr>
                <td>sinter</td>
                <td>key key1 key2...</td>
                <td>返回所有集合的交集</td>
            </tr>
            <tr>
                <td>sinterstore</td>
                <td>key key1 key2...</td>
                <td>将key1与其他集合的交集存储至key集合，返回key集合元素个数</td>
            </tr>
            <tr>
                <td>sunion</td>
                <td>key1 key2...</td>
                <td>返回无序集合之间的并集</td>
            </tr>
            <tr>
                <td>sunionstore</td>
                <td>key key1 key2...</td>
                <td>将key1与其他集合之间的并集存储至key集合，返回key集合元素个数</td>
            </tr>
        </table>
        <li>往集合中添加值的操作，如果集合不存在则会创建集合</li>
    </div>

    <div class="ltable showimg">Stored set有序集合操作</div>
    <div class="img">
        <table>
            <tr>
                <th>命令</th><th>参数</th><th>作用</th>
            </tr>
            <tr>
                <td>zadd</td>
                <td>key score value 【score value...】</td>
                <td>往一个有序集合中添加成员(必须指定score)，返回成功加入的成员个数</td>
            </tr>
            <tr>
                <td>zcard</td>
                <td>key</td>
                <td>返回有序集合的成员个数</td>
            </tr>
            <tr>
                <td>zcount</td>
                <td>key min最小序列 max最大序列</td>
                <td>返回在min和max之间序列拥有的成员个数</td>
            </tr>
            <tr>
                <td>zincrby</td>
                <td>key  increment增量(int可以取负) member</td>
                <td>将一个成员的序列增加一个数并返回新序列</td>
            </tr>
            <tr>
                <td>zscore</td>
                <td>key 成员</td>
                <td>返回指定成员的score排序索引位</td>
            </tr>
            <tr>
                <td>zrange</td>
                <td>key start索引 stop结束 【withscores】</td>
                <td>通过索引（0 -1返回所有成员）返回有序集合的成员</td>
            </tr>
            <tr>
                <td>zrevrange</td>
                <td>key 开始索引 结束索引 【withscores】</td>
                <td>通过索引（0 -1返回所有成员）倒序返回有序集合的成员</td>
            </tr>
            <tr>
                <td>zrangebyscore</td>
                <td>key  (min 【(】max 【withscores】 【limit offset count】</td>
                <td>返回序列区间内有序集合的成员，默认包含max如果有"("不包含</td>
            </tr>
            <tr>
                <td>zrank</td>
                <td>key 成员</td>
                <td>返回成员的索引位置</td>
            </tr>
            <tr>
                <td>zrevrank</td>
                <td>key 成员</td>
                <td>倒序返回所有成员的索引位置</td>
            </tr>
            <tr>
                <td>zrem</td>
                <td>key 成员 【成员...】</td>
                <td>删除有序集合的一个或多个成员</td>
            </tr>
            <tr>
                <td>zremrangebyscore</td>
                <td>key 开始序列 结束序列</td>
                <td>移除有序集合指定序列区间内的所有成员</td>
            </tr>
            <tr>
                <td>zremrangebylex</td>
                <td>key [member [member</td>
                <td>移除集合中两个成员之间的所有成员，返回移除的成员数</td>
            </tr>
            <tr>
                <td>zremrangebyrank</td>
                <td>key start索引位 stop索引位</td>
                <td>移除集合中两个成员之间的所有成员，返回移除的成员数</td>
            </tr>
            <tr>
                <td>zremrangebyscore</td>
                <td>key start索引位置 stop索引位置</td>
                <td>移除有序集合指定索引区间内的所有成员，返回移除的成员数</td>
            </tr>
            <tr>
                <td>zunionstore</td>
                <td>key key1 key2...</td>
                <td>计算给定的一个或多个有序集合的并集，并存储在key中。返回存入的成员数</td>
            </tr>
            <tr>
                <td>zinterstore</td>
                <td>要存储的key key1 [key2...]</td>
                <td>计算给定的一个或多个有序集合的交集，并存储在key中。返回存入的成员数</td>
            </tr>
        </table>
        <li>有序集合的序列号可以重叠，在读取时同序列以ASCII码从小到大排列</li>
        <li>Redis所有区间操作都是包含边界的</li>
        <li>有序集合读取时多个成员的索引号和序列号都是从小到大排序，加入rev（倒转）为大到小排序</li>
    </div>

    <div class="ltable showimg">Redis通用操作命令</div>
    <div class="img">
        <table>
            <tr>
                <th>命令</th><th>作用</th>
            </tr>
            <tr>
                <td>select 数据库名</td>
                <td>选择数据库</td>
            </tr>
            <tr>
                <td>expire key键名 生存时间second</td>
                <td>为key设置一个新的生存秒时</td>
            </tr>
            <tr>
                <td>keys key</td>
                <td>查询当前库有哪些key</td>
            </tr>
            <tr>
                <td>randomkey</td>
                <td>随机返回key</td>
            </tr>
            <tr>
                <td>type key</td>
                <td>判断key的值的数据类型</td>
            </tr>
            <tr>
                <td>exists key键名</td>
                <td>判断key是否存在</td>
            </tr>
            <tr>
                <td>rename key key新键名</td>
                <td>重命名key，新键名存在时会覆盖</td>
            </tr>
            <tr>
                <td>renamenx key键名 key新键名</td>
                <td>重命名key，新键名存在时会失败</td>
            </tr>
            <tr>
                <td>move key键名 数据库名</td>
                <td>将key-value转移到其他数据库</td>
            </tr>
            <tr>
                <td>ttl key键名</td>
                <td>返回key的生存时间秒数，-1为永久有效，-2为该key不存在</td>
            </tr>
            <tr>
                <td>pttl key键名</td>
                <td>返回key的生存毫秒，-1为永久有效，-2为该key不存在</td>
            </tr>

            <tr>
                <td>expireat key键名 生存到的时间戳</td>
                <td>设置key销毁的时间</td>
            </tr>
            <tr>
                <td>persistkey键名</td>
                <td>设置该键永久生存</td>
            </tr>
            <tr>
                <td>Dbsize</td>
                <td>返回当前数据库有多少个key</td>
            </tr>
            <tr>
                <td>flushdb</td>
                <td>清空当前数据库</td>
            </tr>
            <tr>
                <td>flushall</td>
                <td>清空所有数据库</td>
            </tr>
        </table>
        <li>Redis默认有16个数据库，用0~15命名，可以在配置文件中检索databases找到该行配置，后面的数字就是数量，可以修改它</li>
        <li>在使用keys语句获取匹配的key时，可以使用模糊查找，支持?、*、[]，和正则同样意义</li>
    </div>

    <div class="ltable showimg">Redis操作附注</div>
    <div class="img">
        <li>凡是涉及区间操作，Redis都是包含边界的</li>
    </div>
</ul>

<div class="dt">Redis事务</div>
<ul>
    <table>
        <tr>
            <th>命令</th><th>作用</th>
        </tr>
        <tr>
            <td>multi</td><td>开启一个事务</td>
        </tr>
        <tr>
            <td>discard</td><td>清楚所有先前在一个事务中放入的命令，然后恢复正常的连接状态</td>
        </tr>
        <tr>
            <td>exec</td><td>在一个事务中执行所有先前放入的命令，然后恢复正常的连接状态</td>
        </tr>
        <tr>
            <td>watch</td><td>监视一个或多个key</td>
        </tr>
        <tr>
            <td>unwatch</td><td>取消监视</td>
        </tr>
    </table>
    <div class="fu">附注信息</div>
    <li class="fu">Redis的事务只能回滚有语句本身语法错误的语句，而且是自动回滚，其他的错误不支持</li>
    <li class="fu">Redis的监视某个key是在事务过程中该key没有改变，如果改变，附加在之上的执行语句会失败，然后事务回滚</li>
</ul>

<div class="dt">php操作Redis存储系统</div>
<ul>
    <li>php操作Redis需要安装Redis扩展库，安装后使用Redis类下的方法（大小写都可以）</li>
    <li>在实例化Redis类后，使用connect函数连接数据库，它的第一个参数是IP地址，第二个是端口号，第三个是数据库名（Redis数据库名是从0开始递增的自然数），第三个参数默认为0</li>
    <li>在不需要连接Redis存储系统时，可以使用close函数关闭连接，该函数无参数</li>
    <li>Redis类下的方法都是命令头的同名函数，参数也类似，对应传值，在某些情况下，如批量操作、或参数是ex、px、nx、xx家族，会扔到数组里</li>
    <li><a href="https://github.com/phpRedis/phpRedis#hmset" target="blank">更多使用查询</a></li>
</ul>

<div class="dt">Redis和Memcached的比较</div>
<ul>
    <li>redis支持的数据更加多样化，支持list队列、set集合、有序集合、散列表等数据结构的存储</li>
    <li>redis支持数据的持久化，重启的时候可以再次从硬盘加载进行使用</li>
    <li>redis功能更加丰富，支持原子性操作、管道合并处理请求、publish/subscribe、异步出栈等</li>
    <li>redis支持虚拟内存：当物理内存用完时，可以将一些很久没用到的value交换到磁盘</li>
    <li>memcached性能更加优良，能调用多核进行处理。redis只能调用单核，但数据量小的时候，redis性能更好</li>
</ul>

</body>
</html>